#ifndef _ECDHMethods_H_
#define _ECDHMethods_H_
#include <openssl/ssl.h>
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <stdlib.h>
#define ECDH_SIZE 33
 
 using namespace std;

 class ECDHMethods{

public:
	EC_KEY *genECDHtemppubkey(unsigned char *pubkey);
	unsigned char *genECDHsharedsecret(EC_KEY *ecdh, unsigned char *peerkey, size_t secret_len);
	void disp(const char *str, const void *pbuf, const int size);
private:
	inline void handleErrors(){printf("Error occurred.\n");}

 };

 EC_KEY* ECDHMethods::genECDHtemppubkey(unsigned char *pubkey)
{
	int len;
	EC_KEY *ecdh = EC_KEY_new();
	ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);//NID_secp521r1
	EC_KEY_generate_key(ecdh);
	const EC_POINT *point = EC_KEY_get0_public_key(ecdh);
	const EC_GROUP *group = EC_KEY_get0_group(ecdh);
	if(0 == (len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, pubkey, ECDH_SIZE, NULL))) handleErrors();
	//printf("len=%d\n",len);
	return ecdh;
}

unsigned char* ECDHMethods:: genECDHsharedsecret(EC_KEY *ecdh, unsigned char *peerkey, size_t secret_len)
{
	int len;
	unsigned char *shared = (unsigned char *)malloc(ECDH_SIZE);
	const EC_GROUP *group = EC_KEY_get0_group(ecdh);
	EC_POINT *point_peer = EC_POINT_new(group);
	EC_POINT_oct2point(group, point_peer, peerkey, ECDH_SIZE, NULL);
	if(0 == (len = ECDH_compute_key(shared, secret_len, point_peer, ecdh, NULL))) handleErrors();
	return shared;
}

void ECDHMethods::disp(const char *str, const void *pbuf, const int size)
{
	int i=0;
	if(str != NULL){
		printf("%s:\n", str);
	}
	if(pbuf != NULL && size > 0){
		for(i=0;i<size;i++)
			printf("%x ", *((unsigned char *)pbuf+i));
		putchar('\n');
	}
	putchar('\n');
}

 #endif 